local setting = require("meet_your_mods.setting")
local ui      = require("meet_your_mods.ui")

local debug = {
    status = {
        class  = "",
        result = "",
    },
    indent = 0,
    indent_message = "",
}

function debug:sdk_hook(method, pre_hook, post_hook)
    local name = method._typedef_:get_name()
    method:sdk_hook(
        function(parameters)
            self:indent_begin()

            local to_return, message = nil, nil
            if pre_hook then
                to_return, message = pre_hook(parameters)
            end
            log.info(self.indent_message .. name .. (message and " " .. message or ""))
            return to_return or sdk.PreHookResult.CALL_ORIGINAL
        end,
        function(result)
            self:indent_end()

            local to_return, message = nil, nil
            if post_hook then
                to_return, message = post_hook(result)
            end
            if message then
                log.info(self.indent_message .. "end " .. message)
            end
            return to_return or result
        end)
end

function debug:indent_begin()
    self.indent_message = ""
    for _ = 1, self.indent do
        self.indent_message = self.indent_message .. "　"
    end
    self.indent = self.indent + 1
    return self.indent_message
end

function debug:indent_end()
    self.indent         = self.indent - 1
    self.indent_message = ""
    for _ = 1, self.indent do
        self.indent_message = self.indent_message .. "　"
    end
    return self.indent_message
end

function debug:log_info(message, ...)
    log.info(string.format(self.indent_message .. "　" .. message, ...))
end

local function fetch_attributes(class_typedef)
    local is_value_type = class_typedef:is_value_type()
    local attributes    = "Attributes:"

    for _, attribute in pairs(class_typedef:get_fields()) do
        attributes = attributes .. string.format("\n\t%-48." .. #attribute:get_name() .. "s\t: %s%s",
            attribute:get_name(),
            attribute:is_static()
            and (is_value_type
                and ("(" .. tostring(attribute:get_data()) .. ")")
                or "(static)")
            or "",
            attribute:get_type():get_full_name())
    end

    return attributes
end

local function fetch_methods(class_typedef)
    local methods = "Methods:"
    for _, method in pairs(class_typedef:get_methods()) do
        methods = methods .. string.format(#method:get_name() < 48
            and "\n\t%-48." .. #method:get_name() .. "s\t: %s%s"
            or "\n\t%s\t: %s%s",
            method:get_name(),
            method:is_static() and "(static)" or "",
            method:get_return_type():get_full_name())

        local parameters = ""
        local names      = method:get_param_names()
        local types      = method:get_param_types()
        for index = 1, #names do
            parameters = parameters .. string.format(", %s:%s",
                names[index], types[index]:get_full_name())
        end
        if parameters ~= "" then
            parameters = string.sub(parameters, 3)
        end

        methods = methods .. "(" .. parameters .. ")"
    end

    return methods
end

function debug:profile_class()
    if not self.status.class or "" == self.status.class then
        return
    end

    local typedef = sdk.find_type_definition(self.status.class)
    if not typedef then
        self.status.result = "无效类型"
        return
    end

    local profile = string.format("%s: %s:%s\n%s\n%s",
        typedef:is_value_type() and "Enum" or "Class",
        typedef:get_full_name(),
        typedef:get_parent_type() and typedef:get_parent_type():get_full_name() or "None",
        fetch_attributes(typedef),
        fetch_methods(typedef))

    fs.write(string.gsub(".\\profile\\" .. string.gsub(self.status.class, "`%d", "") .. ".txt", "<(.*)>", "{%1}"),
        profile)
    self.status.result = "类型\"" .. string.gsub(self.status.class, "`%d", "") .. "\"探测完毕"
end

function debug:initialize()
    setting:bind_setting(setting.debug, self.status)

    ui:cluster(setting.debug, "Debugger")
    ui:button(setting.debug, "探测", self.profile_class, self)
    ui:sameline(setting.debug)
    ui:input_text(setting.debug, setting.debug, "class", "类型")
    ui:button(setting.debug, "测试", self.test, self)
    ui:sameline(setting.debug)
    ui:text(setting.debug, setting.debug, "result")
end

function debug:normalize()
end

function debug:test()
end

return debug
